/* $Header: dispmon.c,v 2.2 01/10/02 10:26:17 przybyls Exp $ */

/***********************************************************************/
/*                                                                     */
/*                  Copyright Hewlett-Packard Co. 1991                 */
/*                                                                     */
/***********************************************************************/

/***********************************************************************/
/* MODULE NAME: dispmon.c                                              */
/* ============                                                        */
/*                                                                     */
/* Author:                                                             */
/*                                                                     */
/* MODULE PURPOSE: NewtOS task in foreground for managing the          */
/*   repetitive display formatting.                                    */
/*                                                                     */
/*                                                                     */
/*                                                                     */
/***********************************************************************/


/*****************************/
/*   GLOBAL INCLUDE FILES    */
/*****************************/

#include  <typedefs.h>
#include  <p_wkfile.h>
#include  <wkfile.h>
#include  <ramps.h>
#include  <zone_config.h>
#include  <zone_status.h>
#include  <p_status.h>
#include  <status.h>
#include  <keyboard.h>
#include  <display.h>
#include  <i_op.h>
#include  <stddef.h>
#include  <std_ops.h>
#include  <task_pub.h>
#include  <tasks.h>
#include  <msg.h>


/*****************************/
/*   LOCAL INCLUDE FILES     */
/*****************************/


/*****************************/
/*   GLOBAL VARIABLES        */
/*****************************/

void        (* Monitor_Function) (void);
void        (* Line_Function [4]) (LINE Line);
LINE        Lines [4];


U_INT8      Monitor_Clock;
BIT8        Monitor_Done;
U_INT8      Cursor_Line;
U_INT8      ID_Line;
BIT8        Number_Build_Active;
BIT8        Blink_Cursor;
BIT8        Error_Displayed;
BIT8        Monitor_Lockout;


/*****************************/
/*   EXTERNAL VARIABLES      */
/*****************************/

extern BIT8     Pneu_Keys_Enabled; /* revisit */
extern void     PneuFakeDisplay(void);


/*****************************/
/*   LOCAL DEFINES           */
/*****************************/


/*****************************/
/*   STATIC VARIABLES        */
/*****************************/



/*****************************/
/*   IMPLEMENT SECTION       */
/*****************************/


/***********************************************************************/
/* FUNCTION: DisplayMonitor                                            */
/* ========                                                            */
/*                                                                     */
/* PURPOSE: The Display Monitor is the lowest priority NewtOS          */
/*   foreground task.  Its purpose is to reformat the display at about */
/*   10 Hz so we can display changing setpoints and readings.          */
/*                                                                     */
/*        It works by executing an arbitrary display function at the   */
/*   10 Hz rate.  If the function pointer is NULL, it does nothing.    */
/*   There is a handshake with the 10 Hz scheduler in the 512Hz        */
/*   interrupt to keep the monitor from being rescheduled if it hasn't */
/*   finished in a tenth of a second.                                  */
/*                                                                     */
/*        Most of the time the monitor executes the Monitor4Lines      */
/*   function that uses 4 independent Line_Functions to format the     */
/*   lines into the Lines[4] buffer.  This function handles cursor     */
/*   positioning.                                                      */
/*                                                                     */
/***********************************************************************/


void DisplayMonitor(void)
{
   U_INT8  i;

   Monitor_Function = NULL;     /* Task initialization                  */
                                /* NOTE: Monitor_Clock and Monitor_Done */
                                /*       are initialized in DisplayInit */

   for (i = 0; i <=3; i++)      /* Lines Buffer and Monitor4Lines init. */
   {
      Line_Function[i] = NULL;
      (Lines[i])[0]  = 0;
   }

   Cursor_Line = 0;
   ID_Line     = 0;

   Blink_Cursor        = FALSE;
   Error_Displayed     = FALSE;
   Monitor_Lockout     = FALSE;
   Number_Build_Active = FALSE;

                                /* Task Body:   */
   while (TRUE)                 /* Loop Forever */
   {
      (void) Task_wait_sig((TaskSigs)DATA_AVAIL_SIG);

      if ( (Monitor_Function != NULL)  &&
           (Monitor_Lockout  == FALSE) &&
           (Error_Displayed  == FALSE)    )
      {
         (* Monitor_Function)();

         Refresh_Count++;      /* Counter for kbd display refesh */
      }

      if ( Pneu_Keys_Enabled )
      {
/*--------begin change by wangwei----------*/
//          PneuFakeDisplay();
/*--------end change -------------------*/
      }

      Monitor_Done = TRUE;     /* 512 Hz handshake */
   }
}


/***********************************************************************/
/* FUNCTION: Monitor4Lines                                             */
/* ========                                                            */
/*                                                                     */
/* PURPOSE: This function is used to fill out the four display lines   */
/*   in the Lines buffer.  Each line is generated by the corresponding */
/*   Line_Function.  If there is an active line (lines 1, 2, or 3      */
/*   only), the cursor is added at character 20.  If number build is   */
/*   active, the string of numeric characters is overlayed at the end  */
/*   of the line.  If there is an ID_Line, the indicator character is  */
/*   overlayed on the first character of that line (line 1, 2,or 3).   */
/*                                                                     */
/*                                                                     */
/***********************************************************************/

void Monitor4Lines (void)
{
   U_INT8  i;
   U_INT8  endscan;
   BIT8    *lineptr;

   for (i = 0; i <= 3; i++)           /* First fill out the 4 lines in */
   {                                  /*   the Lines buffer            */
      if (Line_Function[i] != NULL)
      {
         (* Line_Function[i]) (Lines[i]);
      }
      else
      {
          (Lines[i])[0] = 0;
      }
   }

   if (Cursor_Line != 0)              /* If the cursor is active,      */
   {                                  /*  add the cursor & possible #  */

   /* First find the end of the cursor line: */

      lineptr = &(Lines[Cursor_Line])[0];
      i = 1;
      endscan = 20;                  /* Force end at 20th character    */

      if (Number_Build_Active)       /* End at 20 - number width if #  */
      {                              /*  must be inserted              */
         endscan -= Number_Tbl->Width;
      }

      while ((i < endscan) && (*lineptr != 0))
      {
         switch (*lineptr)
         {
         case BLINK_CH:
            break;                   /* Don't count blink char */

         case ALTERNATE_CH:
            lineptr++;               /* Don't count aternate char */
            break;                   /* or the following char     */

         default:
            i++;                     /* count all other characters */
            break;
         }

         lineptr++;                  /* advance to next character */
      }

      if (Number_Build_Active)       /* If number build is active,     */
      {
         endscan = 20 - Digits;      /* Reset endscan for #digits to   */
      }                              /* clear entire entry field.      */

      while (i < endscan)            /* Blank fill to endscan position */
      {
         *lineptr = ' ';
         lineptr++;
         i++;
      }

      if (Number_Build_Active)       /* Overlay number image if needed */
      {
         for (i = 0; i < Digits; i++)
         {
            *lineptr = Number_Image[i];
            lineptr++;
         }

         *lineptr = BLINK_CH;        /* Cursor blinks for number build */
         lineptr++;
         *lineptr = '*';
      }
      else
      {
         if (Blink_Cursor)           /* Cursor also blinks if requested */
         {                           /*  by other operations.           */
            *lineptr = BLINK_CH;
            lineptr++;
            *lineptr = '*';          /* Use * cursor                    */
         }
         else
         {
            *lineptr = '<';          /* put cursor at 20th character    */
         }
      }

      lineptr++;
      *lineptr = 0;                  /* add terminator char to active   */
   }                                 /*   line.                         */

   if ( (ID_Line != 0) &&            /* If there is a non-empty ID line,*/
        (Lines[ID_Line])[0] != 0 )   /*  overwrite the first character  */
   {                                 /*  with an indicator.             */

      (Lines[ID_Line])[0] = '*';
   }

   Display4Lines ();             /* Now output the lines to the display */
}


/***********************************************************************/
/* FUNCTION: StartMonitor                                              */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/*                                                                     */
/*                                                                     */
/***********************************************************************/

void StartMonitor ( void (*fn)() )
{
   INTERRUPTS_OFF
   Monitor_Function = fn;
   Monitor_Clock = 0;
   Monitor_Done = TRUE;
   INTERRUPTS_ON
}


/***********************************************************************/
/* FUNCTION: Start4LineMonitor                                         */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/*                                                                     */
/*                                                                     */
/***********************************************************************/

void Start4LineMonitor (void)
{
   INTERRUPTS_OFF
   Monitor_Function = Monitor4Lines;
   Monitor_Clock = 0;
   Monitor_Done = TRUE;
   INTERRUPTS_ON
}


/***********************************************************************/
/* FUNCTION: Only4Lines                                                */
/* ========                                                            */
/*                                                                     */
/* PURPOSE: This function starts the 4 line monitor with the cursor    */
/*    on the input cursor line and the 4 line functions set to the     */
/*    input line functions.                                            */
/*                                                                     */
/*                                                                     */
/*                                                                     */
/***********************************************************************/

void Only4Lines (void (*f0)(LINE a), void (*f1)(LINE b), void (*f2)(LINE c),
                 void (*f3)(LINE d), U_INT8 cursor)
{
   HaltMonitor ();
   Error_Displayed = FALSE;
   Cursor_Line     = cursor;
   ID_Line         = 0;

   Line_Function[0] = f0;
   Line_Function[1] = f1;
   Line_Function[2] = f2;
   Line_Function[3] = f3;

   Start4LineMonitor();
}


/***********************************************************************/
/* FUNCTION: EnableRefresh                                             */
/* ========                                                            */
/*                                                                     */
/* PURPOSE: This function enables the refresh function in the keyboard */
/*    task.  When ON, the monitor is paused and the display as         */
/*    represented by the four line functions is rebuilt using a        */
/*    Scroll (STAY) operation.  This is used by the not-ready and      */
/*    run deviations display.                                          */
/*                                                                     */
/***********************************************************************/

void EnableRefresh (void)
{
   Refresh_Count = 0;
   Active_State.Refresh_On = TRUE;
}


/***********************************************************************/
/* FUNCTION: StopMonitor                                               */
/* ========                                                            */
/*                                                                     */
/* PURPOSE: This function stops the display monitor AND kills the      */
/*    setpoint table operations (eg. LEDs for scrolling).  It is       */
/*    used for commands that are initializing a new display or         */
/*    monitor function.                                                */
/*                                                                     */
/*                                                                     */
/***********************************************************************/

void StopMonitor (void)
{
   Monitor_Function      = NULL;
   Error_Displayed       = FALSE;
   Info_Displayed        = FALSE;
   Blink_Cursor          = FALSE;
   Number_Build_Active   = FALSE;
   Cursor_Line           = 0;
   ID_Line               = 0;
   Active_State.Refresh_On = FALSE;
   Active_State.ScrollFn = NULL;
   Active_State.HelpFn   = NULL;
   Active_State.Setpt_Tbl = NULL;

   DisableWatchMode();
/* TURN_SCROLL_UP_LED_OFF();     */
/* TURN_SCROLL_DOWN_LED_OFF();   */
}


/***********************************************************************/
/* FUNCTION: HaltMonitor                                               */
/* ========                                                            */
/*                                                                     */
/* PURPOSE: This function stops the display monitor but leaves the     */
/*    scroll function and scroll LEDs alone.  It is used for scroll    */
/*    table operations (eg: scrolling functions).                      */
/*                                                                     */
/***********************************************************************/

void HaltMonitor (void)
{
   Monitor_Function = NULL;
}


/***********************************************************************/
/* FUNCTION: PauseMonitor                                              */
/* ========                                                            */
/*                                                                     */
/* PURPOSE: This function pauses the operation of the display monitor  */
/*    so that error or help messages can be displayed.  Monitor        */
/*    function can easily be resumed via the clear key.                */
/*                                                                     */
/***********************************************************************/

void PauseMonitor (void)
{
   Error_Displayed = TRUE;
}


void ResumeMonitor (void)
{
   Error_Displayed = FALSE;   /* only for use with scroll tables !! */
   Info_Displayed  = FALSE;
}

